home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
System Booster
/
System Booster.iso
/
Texteditors
/
XDME
/
Src
/
Var
/
VarStack.c
< prev
Wrap
C/C++ Source or Header
|
1996-09-26
|
8KB
|
324 lines
/******************************************************************************
MODUL
varstack.c
DESCRIPTION
Variable Stack for DME/XDME
NOTES
-/-
BUGS
<none known>
TODO
-/-
EXAMPLES
-/-
SEE ALSO
vars.c
INDEX
HISTORY
05-12-92 b_noll created
26-08-93 VSTK_drop added
24-06-94 renamed VARS to VRST
******************************************************************************/
/*
** (C)Copyright 1992 by Bernd Noll for null/zero-soft
** All Rights Reserved
**
** RCS Header: $Id: varstack.c,v 1.65 92/12/05 12:47:24 b_noll Exp $
**
**
*!**********************************************************
*!
*! Variable Stacking:
*!
*! Stacking for all structures, which may be read and
*! written via GetTypedVar()
*! (Please notice that stackable are only variables,
*! not macros, menues or mappings (they are stackable, but
*! popping or picking might fail))
*!
*! Users should be aware to pop their entries from the stack
*! when they are needed not any more
*! (We have NOT planned to create a garbage-collector :-))
*!
************************************************************
**
** Implementator's note:
**
** variable stacking is done in a quiet simple way:
** all variables are searched with gettypedvar and their types
** are used as Node.ln_Type - entry
**
** currently (12-92) we use the same structure for storing variables
** on varstack which is used for storage in the main variable
** lists, but I preferred redefining that structure, as this method
** gives us the possibility of changing our definitions locally.
** (This is as we are just implementing AVL-Trees for Varstorage)
*/
/**************************************
Includes
**************************************/
#include "defs.h"
#ifdef PATCH_NULL
#include "COM.h"
#include "libs/AUTO.h"
#endif
/**************************************
Globale Exports
**************************************/
Prototype void do_pushVAR (void);
Prototype void do_pickVAR (void);
Prototype void do_popVAR (void);
Prototype void do_swapVAR (void);
Prototype void do_purgeVAR (void);
/**************************************
Interne Defines & Strukturen
**************************************/
#define MLIST struct MinList
#define MNODE struct MinNode
static MLIST varstack =
{ (MNODE*)&varstack.mlh_Tail, NULL, (MNODE*)&varstack.mlh_Head };
typedef struct _VRST
{
NODE Node;
char* Str;
} VRST;
/**************************************
Interne Prototypes
**************************************/
void VSTK_drop (VRST *);
/**************************************
Impementation
**************************************/
/*
*! >PUSHVAR varname
*!
*! push the contents of the variable varname onto variable-stack
*!
*/
void do_pushVAR (void)
{
VRST *v;
int type;
if ((v = malloc (sizeof (VRST))))
{ /* allocate a node */
setmem(v, sizeof (VRST), 0);
v->Node.ln_Name = strdup (av[1]); /* and space for name and value */
v->Str = GetTypedVar (av[1], &type);
if (v->Node.ln_Name && v->Str)
{ /* if its done, fill in all values and push the node onto the varstack */
v->Node.ln_Type = type;
AddHead((LIST*)&varstack, (NODE*)v);
} else
{ /* else free all what You have already allocated */
if (v->Node.ln_Name)
{
error ("%s: failure!\nno memory", av[0]);
free(v->Node.ln_Name);
} /* if */
if (v->Str)
{
error ("%s: failure!\nno memory or unknown variable", av[0]);
free(v->Str);
} /* if */
free(v);
} /* if (not) malloced|found */
} else
{
error ("%s: no memory for stack-entry", av[0]);
} /* if (not) malloced */
} /* do_pushVAR */
/*
*! >POPVAR varname
*!
*! get the latest to variable-stack pushed contents of the variable
*! varname back and free the stack-entry
*!
*/
void do_popVAR (void)
{
VRST *v;
if ((v = (VRST *)FindName((LIST*)&varstack, av[1])))
{ /* if there is a matching stack-entry */
SetTypedVar(av[1], v->Str, v->Node.ln_Type); /* do a setvar to its name with its contents */
VSTK_drop (v); /* and drop the entry */
} else
{
error ("%s: stackentry %s not found", av[0], av[1]);
} /* if (not) found */
} /* do_popVAR */
/*
*! >PICKVAR varname
*!
*! get the latest to variable-stack pushed contents of the variable
*! varname back without freeing the stack-entry
*!
*/
void do_pickVAR (void)
{
VRST *v;
if ((v = (VRST *)FindName((LIST*)&varstack, av[1])))
{ /* if there is a matching stack-entry */
SetTypedVar(av[1], v->Str, v->Node.ln_Type); /* do a setvar to its name with its contents */
} else
{
error ("%s: stackentry %s not found", av[0], av[1]);
} /* if (not) found */
} /* do_pickVAR */
/*
*! >SWAPVAR varname
*!
*! swap the contents of the variable varname and of its first occurancy in variable-stack
*!
** this is not a very effective way of change, I would say,
** but it is one of the shortest
*/
void do_swapVAR (void)
{
VRST *v;
if ((v = (VRST *)FindName((LIST*)&varstack, av[1])))
{ /* if there is a matching stack-entry */
Remove((NODE*)v); /* remove it */
do_pushVAR(); /* push the variables current contents onto stack */
AddHead((LIST*)&varstack, (NODE*)v); /* set the elder stack-entry before that new node */
do_popVAR(); /* and then pop it into the variable */
} else
{
error ("%s: stackentry %s not found", av[0], av[1]);
} /* if (not) found */
} /* do_swapVAR */
/*
*! >PURGEVAR varname
*!
*! remove all entries with the name varname from varstack
*!
*/
void do_purgeVAR (void)
{
VRST *v;
VARS *w;
/* ---- we cannot use GetSucc() here, since we would take the successor of a freed node =8-( */
for (v = (VRST *)varstack.mlh_Head; (w = (VRST *)v->Node.ln_Succ) != NULL; v = w) /* for all nodes ... */
if (strcmp(v->Node.ln_Name, av[1]) == 0) /* if they match ... */
VSTK_drop (v); /* drop them ... */
} /* do_purgeVAR */
void do_dropVAR (void)
{
VRST *v;
if ((v = (VRST *)FindName((LIST*)&varstack, av[1]))) /* find them first matching node */
VSTK_drop (v); /* ... and drop it */
} /* do_dropVAR */
void VSTK_drop (VRST *v)
{
/* ---- Remove an entry from the stack, and free its contents and itself */
if (v)
{
Remove((NODE*)v);
free(v->Str);
free(v->Node.ln_Name);
free(v);
} /* if */
} /* VSTK_drop */
#ifdef PATCH_NULL
static const
struct CommandNode VSTK_Commands[] =
{
{ENODE("pickvar"), 1, CF_VWM|CF_COK|CF_ICO, (FPTR)do_pickVAR },
{ENODE("popvar"), 1, CF_VWM|CF_COK|CF_ICO, (FPTR)do_popVAR },
{ENODE("pushvar"), 1, CF_VWM|CF_COK|CF_ICO, (FPTR)do_pushVAR },
{ENODE("purgevar"), 1, CF_VWM|CF_COK|CF_ICO, (FPTR)do_purgeVAR },
{ENODE("swapvar"), 1, CF_VWM|CF_COK|CF_ICO, (FPTR)do_swapVAR },
{ENODE("dropvar"), 1, CF_VWM|CF_COK|CF_ICO, (FPTR)do_dropVAR },
};
MK_AUTOINIT(VSTK_Init)
{
int i;
NewList ((struct List*)&varstack);
for (i = sizeof (VSTK_Commands)/sizeof (struct CommandNode) - 1;i >= 0; --i)
COM_Add (&VSTK_Commands[i]);
} /* VSTK_Init */
MK_AUTOEXIT(VSTK_Exit)
{
int i;
APTR lock;
VRST*v;
while ((v = GetHead (&varstack)))
VSTK_drop (v);
for (i = sizeof (VSTK_Commands)/sizeof (struct CommandNode) - 1; (i >= 0); DEC(i))
if ((lock = COM_Lock (VSTK_Commands[i].Node.ln_Name)))
COM_Remove (lock);
} /* VSTK_Exit */
#endif
/******************************************************************************
***** ENDE varstack.c
******************************************************************************/